import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

// 注册 dayjs 插件
dayjs.extend(utc);
dayjs.extend(timezone);

/**
 * UTC 时间转换工具类
 * 支持输入：UTC 时间字符串（含 Z 后缀）、Date 对象（内部自动识别是否为 UTC 时间）
 * 默认输出：北京时间（Asia/Shanghai，UTC+8），格式：YYYY-MM-DD HH:mm:ss
 */
export class UtcDateFormatter {
  /**
   * 核心转换方法（支持 string/Date 输入）
   * @param utcInput - 待转换的 UTC 输入（string：如 "2025-09-11T22:00:56.000Z"；Date：如 new Date("2025-09-11T22:00:56.000Z")）
   * @param targetTimezone - 目标时区（默认：Asia/Shanghai）
   * @param formatStr - 输出格式（默认：YYYY-MM-DD HH:mm:ss）
   * @returns 格式化后的时间字符串 | null（转换失败时）
   */
  public static convertUtcToLocal(
    utcInput: string | Date,
    targetTimezone: string = 'Asia/Shanghai',
    formatStr: string = 'YYYY-MM-DD HH:mm:ss'
  ): string | null {
    try {
      // 1. 校验输入有效性
      if (!utcInput) {
        throw new Error('输入不能为空，请传入 UTC 时间字符串或 Date 对象');
      }

      // 2. 处理输入：区分 string 和 Date 类型
      let dayjsInstance: dayjs.Dayjs;
      if (typeof utcInput === 'string') {
        // 处理字符串输入：必须是含 Z 后缀的 UTC 格式
        if (!utcInput.endsWith('Z')) {
          throw new Error(`无效的 UTC 字符串格式：${utcInput}，请传入如 "2025-09-11T22:00:56.000Z" 的字符串`);
        }
        dayjsInstance = dayjs(utcInput).utc(); // 显式标记为 UTC 时间
      } else if (utcInput instanceof Date) {
        // 处理 Date 对象：先判断是否为有效 Date（避免 Invalid Date）
        if (isNaN(utcInput.getTime())) {
          throw new Error(`无效的 Date 对象：${utcInput}`);
        }
        // 无论 Date 对象是本地时区还是 UTC 时区，统一按 UTC 时间解析
        dayjsInstance = dayjs(utcInput).utc();
      } else {
        throw new Error(`不支持的输入类型：${typeof utcInput}，仅支持 string 或 Date`);
      }

      // 3. 切换时区 + 格式化输出
      const formattedTime = dayjsInstance.tz(targetTimezone).format(formatStr);
      if (!formattedTime) {
        throw new Error(`时间转换失败，输入：${JSON.stringify(utcInput)}`);
      }

      return formattedTime;
    } catch (error) {
      console.error('[UtcDateFormatter] 转换出错：', (error as Error).message);
      return null;
    }
  }

  /**
   * 快捷方法：转北京时间（默认格式）
   */
  public static convertToBeijingTime(utcInput: string | Date): string | null {
    return this.convertUtcToLocal(utcInput, 'Asia/Shanghai', 'YYYY-MM-DD HH:mm:ss');
  }

  /**
   * 快捷方法：转 UTC 原时间（不切换时区）
   */
  public static convertToUtcTime(utcInput: string | Date): string | null {
    return this.convertUtcToLocal(utcInput, 'UTC', 'YYYY-MM-DD HH:mm:ss');
  }
}